package gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;

import javax.swing.Box;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;

public class XYZFrame extends JFrame {

	private JTextArea sourceArea;
	// private JSplitPane console;
	// private JTextArea tokens;
	private JScrollPane tokenTableScrollPane;
	private JTable tokenTable;
	private JTextArea warningAndErrorArea;
	private Hashtable<String, Integer> tokenCount = new Hashtable<String, Integer>();
	private XYZParser parser;
	private JSplitPane splitPane;
	private DefaultTableModel tableModel;
	private boolean initedOnce = false;

	public static void main(String args[]) {
		XYZFrame frame = new XYZFrame();
		frame.setSize(800, 600);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public XYZFrame() {
		super();
		addMenu();
		addPanels();
	}

	private void addPanels() {

		Box sourceBox = Box.createVerticalBox();
		sourceArea = new JTextArea();
		sourceArea.setSize(400, 600);
		sourceArea.setWrapStyleWord(true);
		sourceBox.add(Box.createHorizontalStrut(400));
		// sourceBox.add(new JScrollPane(sourceArea));
		sourceBox.add(sourceArea);
		// tokens = new JTextArea();
		// tokens.setEditable(false);
		// Box tokensBox = Box.createHorizontalBox();
		// tokensBox.add(tokens);
		// tokensBox.add(Box.createVerticalStrut(200));

		tableModel = new DefaultTableModel();
		tokenTable = new JTable(tableModel);
		tableModel.addColumn("ID/Keyword");
		tableModel.addColumn("Count");

		tokenTableScrollPane = new JScrollPane(tokenTable);

		// console = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tokensBox,
		// tokenTableScrollPane);

		splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sourceBox,
				tokenTableScrollPane);
		splitPane.setContinuousLayout(true);
		splitPane.setOneTouchExpandable(true);

		warningAndErrorArea = new JTextArea();
		warningAndErrorArea.setEditable(false);

		Box warningBox = Box.createVerticalBox();
		warningBox.add(new JLabel("Warnings and errors"));
		warningBox.add(warningAndErrorArea);

		JSplitPane outerSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
				splitPane, warningBox);

		add(outerSplitPane, BorderLayout.CENTER);
	}

	private void addMenu() {
		JMenuBar menuBar = new JMenuBar();
		add(menuBar, BorderLayout.NORTH);

		JMenu fileMenu = new JMenu("File");
		fileMenu.setMnemonic('f');
		menuBar.add(fileMenu);

		JMenu parseMenu = new JMenu("Parse");
		parseMenu.setMnemonic('p');
		// menuBar.add(parseMenu);

		JMenu helpMenu = new JMenu("Help");
		helpMenu.setMnemonic('h');
		menuBar.add(helpMenu);

		JMenuItem openItem = new JMenuItem("Open");
		openItem.setMnemonic('o');
		openItem.addActionListener(new OpenFileActionListener());
		fileMenu.add(openItem);

		JMenuItem saveItem = new JMenuItem("Save Output");
		saveItem.setMnemonic('s');
		saveItem.addActionListener(new SaveFileActionListener());
		fileMenu.add(saveItem);

		JMenuItem exitItem = new JMenuItem("Exit");
		exitItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		exitItem.setMnemonic('x');
		fileMenu.add(exitItem);

		JMenuItem lexicalItem = new JMenuItem("Lexical Analysis");
		lexicalItem.setMnemonic('l');
		parseMenu.add(lexicalItem);

		JMenuItem aboutItem = new JMenuItem("About");
		aboutItem.setMnemonic('a');
		aboutItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(XYZFrame.this,
						"Team YY, Max, Rex, White, Mega");
			}
		});
		helpMenu.add(aboutItem);

	}

	class OpenFileActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			while (tableModel.getRowCount() > 0)
				tableModel.removeRow(0);

			JFileChooser chooser = new JFileChooser();
			chooser.setFileFilter(new DefaultFileFilter());
			int returnVal = chooser.showOpenDialog(XYZFrame.this);
			if (returnVal != JFileChooser.APPROVE_OPTION)
				return;
			File file = chooser.getSelectedFile();

			try {
				FileReader reader = new FileReader(file);
				StringBuffer buffer = new StringBuffer(1024);
				char buff[] = new char[1024];
				while (reader.read(buff) != -1) {
					buffer.append(buff);
				}
				reader.close();
				reader = null;
				sourceArea.setText(buffer.toString());

				FileInputStream inputStream = new FileInputStream(file);

				if (!initedOnce) {
					parser = new XYZParser(inputStream);
					initedOnce = true;
				} else {
					XYZParser.ReInit(inputStream);
				}

				Token currentToken = null;
				int count[] = new int[XYZParserConstants.tokenImage.length];
				do {
					try {
						currentToken = XYZParser.getNextToken();
						count[currentToken.kind]++;
					} catch (Error e1) {
						System.out.println(e1.toString());
						warningAndErrorArea.setText(e1.toString());
						break;
					}
				} while (!currentToken.image.equals(""));
				for (int i = 0; i < count.length; i++) {
					tokenCount.put(XYZParserConstants.tokenImage[i], count[i]);
					tableModel.addRow(new Object[] {
							XYZParserConstants.tokenImage[i],
							String.valueOf(count[i]) });
				}
				inputStream.close();
			} catch (FileNotFoundException ex) {
				ex.printStackTrace();
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
	}

	class SaveFileActionListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JFileChooser chooser = new JFileChooser();
			int returnVal = chooser.showOpenDialog(XYZFrame.this);
			if (returnVal != JFileChooser.APPROVE_OPTION)
				return;
			File file = chooser.getSelectedFile();
			if (file.exists()) {
				int confirm = JOptionPane.showConfirmDialog(XYZFrame.this,
						"File already exists, OVERWRITE?", "File Overwrite",
						JOptionPane.YES_NO_OPTION);
				if (confirm != JOptionPane.YES_OPTION)
					return;
			}
			try {
				FileWriter writer = new FileWriter(file);
				writer.write("ID/Keyword\t\t\tCount\n");
				Iterator<String> it = tokenCount.keySet().iterator();
				while (it.hasNext()) {
					String key = it.next();
					writer.write(key);
					for (int i = 0; i < 4 - key.length() / 8; i++)
						writer.write('\t');
					writer.write(String.valueOf(tokenCount.get(key)));
					writer.write('\n');
				}
				writer.close();
				writer = null;
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}

		}
	}

	class DefaultFileFilter extends FileFilter {

		@Override
		public boolean accept(File f) {
			if (f.isDirectory()) {
				return true;
			}
			String fileName = f.getName();
			if (fileName.length() - fileName.lastIndexOf(".java") == 5) {
				return true;
			}
			return false;
		}

		@Override
		public String getDescription() {
			return "Only minijava files are accepted";
		}
	}
}
